/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2024 Realtek Corporation. All rights reserved
 */

#include "../r8169_compat.h"
#include "../r8169_dash.h"
#include "../r8169_hw.h"
#include "../r8169_phy.h"
#include "rtl8168ep.h"

/* For RTL8168EP, CFG_METHOD_23,27,28 */

/* -------------------------------------MAC 8168EP------------------------------------ */

static void
rtl8168_set_mac_mcu_8168ep_1(struct rtl_hw *hw)
{
	u16 i;
	static const u16 mcu_patch_code_8168ep_1[] = {
		0xE008, 0xE0D3, 0xE0D6, 0xE0D9, 0xE0DB, 0xE0DD, 0xE0DF, 0xE0E1, 0xC251,
		0x7340, 0x49B1, 0xF010, 0x1D02, 0x8D40, 0xC202, 0xBA00, 0x2C3A, 0xC0F0,
		0xE8DE, 0x2000, 0x8000, 0xC0B6, 0x268C, 0x752C, 0x49D4, 0xF112, 0xE025,
		0xC2F6, 0x7146, 0xC2F5, 0x7340, 0x49BE, 0xF103, 0xC7F2, 0xE002, 0xC7F1,
		0x304F, 0x6226, 0x49A1, 0xF1F0, 0x7222, 0x49A0, 0xF1ED, 0x2525, 0x1F28,
		0x3097, 0x3091, 0x9A36, 0x752C, 0x21DC, 0x25BC, 0xC6E2, 0x77C0, 0x1304,
		0xF014, 0x1303, 0xF014, 0x1302, 0xF014, 0x1301, 0xF014, 0x49D4, 0xF103,
		0xC3D7, 0xBB00, 0xC618, 0x67C6, 0x752E, 0x22D7, 0x26DD, 0x1505, 0xF013,
		0xC60A, 0xBE00, 0xC309, 0xBB00, 0xC308, 0xBB00, 0xC307, 0xBB00, 0xC306,
		0xBB00, 0x25C8, 0x25A6, 0x25AC, 0x25B2, 0x25B8, 0xCD08, 0x0000, 0xC0BC,
		0xC2FF, 0x7340, 0x49B0, 0xF04E, 0x1F46, 0x308F, 0xC3F7, 0x1C04, 0xE84D,
		0x1401, 0xF147, 0x7226, 0x49A7, 0xF044, 0x7222, 0x2525, 0x1F30, 0x3097,
		0x3091, 0x7340, 0xC4EA, 0x401C, 0xF006, 0xC6E8, 0x75C0, 0x49D7, 0xF105,
		0xE036, 0x1D08, 0x8DC1, 0x0208, 0x6640, 0x2764, 0x1606, 0xF12F, 0x6346,
		0x133B, 0xF12C, 0x9B34, 0x1B18, 0x3093, 0xC32A, 0x1C10, 0xE82A, 0x1401,
		0xF124, 0x1A36, 0x308A, 0x7322, 0x25B5, 0x0B0E, 0x1C00, 0xE82C, 0xC71F,
		0x4027, 0xF11A, 0xE838, 0x1F42, 0x308F, 0x1B08, 0xE824, 0x7236, 0x7746,
		0x1700, 0xF00D, 0xC313, 0x401F, 0xF103, 0x1F00, 0x9F46, 0x7744, 0x449F,
		0x445F, 0xE817, 0xC70A, 0x4027, 0xF105, 0xC302, 0xBB00, 0x2E08, 0x2DC2,
		0xC7FF, 0xBF00, 0xCDB8, 0xFFFF, 0x0C02, 0xA554, 0xA5DC, 0x402F, 0xF105,
		0x1400, 0xF1FA, 0x1C01, 0xE002, 0x1C00, 0xFF80, 0x49B0, 0xF004, 0x0B01,
		0xA1D3, 0xE003, 0x0B02, 0xA5D3, 0x3127, 0x3720, 0x0B02, 0xA5D3, 0x3127,
		0x3720, 0x1300, 0xF1FB, 0xFF80, 0x7322, 0x25B5, 0x1E28, 0x30DE, 0x30D9,
		0x7264, 0x1E11, 0x2368, 0x3116, 0xFF80, 0x1B7E, 0xC602, 0xBE00, 0x06A6,
		0x1B7E, 0xC602, 0xBE00, 0x0764, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00,
		0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00,
		0x0000
	};

	rtl_hw_disable_mac_mcu_bps(hw);

	for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_1); i++)
		rtl_mac_ocp_write(hw, 0xF800 + i * 2, mcu_patch_code_8168ep_1[i]);

	rtl_mac_ocp_write(hw, 0xFC26, 0x8000);

	rtl_mac_ocp_write(hw, 0xFC28, 0x2549);
	rtl_mac_ocp_write(hw, 0xFC2A, 0x06A5);
	rtl_mac_ocp_write(hw, 0xFC2C, 0x0763);
}

static void
rtl8168_set_mac_mcu_8168ep_2(struct rtl_hw *hw)
{
	u16 i;
	static const u16 mcu_patch_code_8168ep_2[] = {
		0xE008, 0xE017, 0xE052, 0xE056, 0xE058, 0xE05A, 0xE05C, 0xE05E, 0xC50F,
		0x76A4, 0x49E3, 0xF007, 0x49C0, 0xF103, 0xC607, 0xBE00, 0xC606, 0xBE00,
		0xC602, 0xBE00, 0x0BDA, 0x0BB6, 0x0BBA, 0xDC00, 0xB400, 0xB401, 0xB402,
		0xB403, 0xB404, 0xC02E, 0x7206, 0x49AE, 0xF1FE, 0xC12B, 0x9904, 0xC12A,
		0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, 0xF117, 0xC123, 0xC223,
		0xC323, 0xE808, 0xC322, 0xE806, 0xC321, 0xE804, 0xC320, 0xE802, 0xE00C,
		0x740E, 0x49CE, 0xF1FE, 0x9908, 0x990A, 0x9A0C, 0x9B0E, 0x740E, 0x49CE,
		0xF1FE, 0xFF80, 0xB004, 0xB003, 0xB002, 0xB001, 0xB000, 0xC604, 0xC002,
		0xB800, 0x1FC8, 0xE000, 0xE8E0, 0xF128, 0x0002, 0xFFFF, 0xF000, 0x8001,
		0x8002, 0x8003, 0x8004, 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x0490, 0xC602,
		0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602,
		0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000
	};

	rtl_hw_disable_mac_mcu_bps(hw);

	for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_2); i++)
		rtl_mac_ocp_write(hw, 0xF800 + i * 2, mcu_patch_code_8168ep_2[i]);

	rtl_mac_ocp_write(hw, 0xFC26, 0x8000);

	rtl_mac_ocp_write(hw, 0xFC28, 0x0BB3);
	if (!rtl8168_check_dash_other_fun_present(hw))
		rtl_mac_ocp_write(hw, 0xFC2A, 0x1FC7);
}

/* ------------------------------------PHY 8168FP------------------------------------- */

static void
rtl8168_set_phy_mcu_8168ep_2(struct rtl_hw *hw)
{
	unsigned int gphy_val;

	rtl_set_phy_mcu_patch_request(hw);

	rtl_mdio_write(hw, 0x1f, 0x0A43);
	rtl_mdio_write(hw, 0x13, 0x8146);
	rtl_mdio_write(hw, 0x14, 0x8700);
	rtl_mdio_write(hw, 0x13, 0xB82E);
	rtl_mdio_write(hw, 0x14, 0x0001);

	rtl_mdio_write(hw, 0x1F, 0x0A43);

	rtl_mdio_write(hw, 0x13, 0x83DD);
	rtl_mdio_write(hw, 0x14, 0xAF83);
	rtl_mdio_write(hw, 0x14, 0xE9AF);
	rtl_mdio_write(hw, 0x14, 0x83EE);
	rtl_mdio_write(hw, 0x14, 0xAF83);
	rtl_mdio_write(hw, 0x14, 0xF1A1);
	rtl_mdio_write(hw, 0x14, 0x83F4);
	rtl_mdio_write(hw, 0x14, 0xD149);
	rtl_mdio_write(hw, 0x14, 0xAF06);
	rtl_mdio_write(hw, 0x14, 0x47AF);
	rtl_mdio_write(hw, 0x14, 0x0000);
	rtl_mdio_write(hw, 0x14, 0xAF00);
	rtl_mdio_write(hw, 0x14, 0x00AF);
	rtl_mdio_write(hw, 0x14, 0x0000);

	rtl_mdio_write(hw, 0x13, 0xB818);
	rtl_mdio_write(hw, 0x14, 0x0645);

	rtl_mdio_write(hw, 0x13, 0xB81A);
	rtl_mdio_write(hw, 0x14, 0x0000);

	rtl_mdio_write(hw, 0x13, 0xB81C);
	rtl_mdio_write(hw, 0x14, 0x0000);

	rtl_mdio_write(hw, 0x13, 0xB81E);
	rtl_mdio_write(hw, 0x14, 0x0000);

	rtl_mdio_write(hw, 0x13, 0xB832);
	rtl_mdio_write(hw, 0x14, 0x0001);

	rtl_mdio_write(hw, 0x1F, 0x0A43);
	rtl_mdio_write(hw, 0x13, 0x0000);
	rtl_mdio_write(hw, 0x14, 0x0000);
	rtl_mdio_write(hw, 0x1f, 0x0B82);
	gphy_val = rtl_mdio_read(hw, 0x17);
	gphy_val &= ~BIT_0;
	rtl_mdio_write(hw, 0x17, gphy_val);
	rtl_mdio_write(hw, 0x1f, 0x0A43);
	rtl_mdio_write(hw, 0x13, 0x8146);
	rtl_mdio_write(hw, 0x14, 0x0000);

	rtl_clear_phy_mcu_patch_request(hw);
}

void
hw_mac_mcu_config_8168ep(struct rtl_hw *hw)
{
	if (hw->NotWrMcuPatchCode)
		return;

	switch (hw->mcfg) {
	case CFG_METHOD_27:
		rtl8168_set_mac_mcu_8168ep_1(hw);
		break;
	case CFG_METHOD_28:
		rtl8168_set_mac_mcu_8168ep_2(hw);
		break;
	}
}

void
hw_phy_mcu_config_8168ep(struct rtl_hw *hw)
{
	switch (hw->mcfg) {
	case CFG_METHOD_28:
		rtl8168_set_phy_mcu_8168ep_2(hw);
		break;
	}
}
